The Lazy ActionScript Developer’s Way to Stream Flash Video

In this final installment of my tutorial on YouTube hacking, I’m going to show how to build the FLV URL for YouTube videos and start streaming the FLV in your ActionScript application. As you will notice, this is very little work, because it is based on the streaming example in the AS3 language reference. I’m being lazy.

A recap of the ActionScript 3.0 YouTube player series:

Constructing the YouTube video URL

There are several ways to get to this one. You could fire up FireBug and check the network logs, or you could check Shane’s code and open his Main.as class. Skip to line 67 and you’ll see:

case YouTube.VIDEOID :
	fvc.play(YouTube.FLVUrl + e.value.id + "&t=" + e.value.t);
	break;

What this means: to construct the full URL to a YouTube Flash video file, you take the base URL and add both the video id and the T-parameter as arguments. An example URL might look like this:

http://www.youtube.com/get_video?video_id=v6ICEpYEcD8&t=OEgsToPDskIltmXs7gZ89kc2a3Z1SRGN

(I have not linked the URL, as it probably won’t work, because the T-parameter changes over time)

Streaming the FLV

For this one I’m going to use the existing ActionScript 3 classes. In particular flash.net.NetConnection and flash.net.NetStream. In the following code I’m adding the language reference example to the already existing code.

What happens might not be clear when you look at the code. That’s because we use a lot of event handlers. But if you take your time and go over the code it will become clear. What goes on is this:

  1. We create a NetConnection.
  2. If this goes well the netStatusHandler is called with the event “NetConnection.Connect.Success”. This in turn will launch the YouTube query to locate a video and create the URL to play it.
  3. This part we’ve already discussed in previous posts:
    1. Create the YouTube object and add listeners.
    2. Get a list of videos for a tag.
    3. When that lists returns, select the first one and get the T-parameter from our PHP script
  4. We construct the YouTube FLV URL (see above) and call the play method.
  5. The play method creates a NetStream and Video object and starts the play the video.

Everything else you see is basically code to handle possible errors:

package
{
  import com.flashdynamix.events.CustomEvent;
  import com.flashdynamix.services.YouTube;
  import flash.display.Sprite;
  import flash.events.AsyncErrorEvent;
  import flash.events.ErrorEvent;
  import flash.events.Event;
  import flash.events.NetStatusEvent;
  import flash.events.SecurityErrorEvent;
  import flash.media.Video;
  import flash.net.NetConnection;
  import flash.net.NetStream;

  public class Main extends Sprite {
    private var connection : NetConnection;
    private var stream : NetStream;
    private var video : Video;
    private var yt : YouTube;

    public function Main():void {
      if (stage) init();
      else addEventListener(Event.ADDED_TO_STAGE, init);
    }

    private function init(e:Event = null):void {
      removeEventListener(Event.ADDED_TO_STAGE, init);

      trace("creating NetConnection");
      connection = new NetConnection();
      connection.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
      connection.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
      connection.connect(null);
    }

    private function netStatusHandler(event : NetStatusEvent):void {
      switch (event.info.code) {
        case "NetConnection.Connect.Success":
          connectStream();
          break;
        case "NetStream.Play.StreamNotFound":
          trace("Unable to locate video");
          break;
        case "NetStream.Play.Start":
          trace("start playing");
          break;
        case "NetStream.Play.Stop" :
          trace("stop playing");
          break;
      }
    }

    private function securityErrorHandler(event:SecurityErrorEvent):void {
      trace("securityErrorHandler: " + event);
    }

    private function connectStream():void {
      trace("start YouTube search");
      yt = new YouTube();
      yt.addEventListener(Event.COMPLETE, onLoaded);
      yt.addEventListener(ErrorEvent.ERROR, onError);
      yt.videosForTag("lego");
    }

    private function onLoaded(e:CustomEvent):void {
      switch (e.id) {
        case YouTube.SEARCH :
          trace("search finished");
          try {
            trace("first item : " + e.value.items[0].title + " - " + e.value.items[0].link);
          } catch (evt:ArgumentError) {
            trace("ERROR : No Videos For Tag");
          }
          trace("requesting the video id and t-parameter");
          yt.videoId(e.value.items[0].link);
          break;
        case YouTube.VIDEOID :
          trace("loaded: video id = " + e.value.id + " and T-parameter = " + e.value.t);
          play(YouTube.FLVUrl + e.value.id + "&t=" + e.value.t);
          break;
      }
    }

    private function onError(e:ErrorEvent):void {
      trace("IOError : " + e );
    }

    private function play(url:String):void {
      trace("playing: " + url);
      stream = new NetStream(connection);
      stream.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
      stream.addEventListener(AsyncErrorEvent.ASYNC_ERROR, asyncErrorHandler);
      video = new Video();
      video.attachNetStream(stream);
      stream.play(url);
      addChild(video);
    }

    private function asyncErrorHandler(event:AsyncErrorEvent):void {
      // ignore AsyncErrorEvent events.
    }
  }
}

I’ve put all files we used in the tutorials in a handy zip file. Just expand and open in FlashDevelop.

Conclusion

In this 5th and final post of the series I have shown how to actually stream the YouTube FLV. It was particularly easy because Flash already has everything you need. It’s a matter of finding the right classes and using them.

That wraps up the 5 part tutorial. Feel free to leave a comment if you found this useful or not. I’m also open for suggestions for improvements or other subjects for future tutorials.

Image credit.